home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 August / macformat-027.iso / mac / Shareware City / Developers / Oberon⁄F / Form / Mod / Controllers (.txt) < prev    next >
Encoding:
Oberon Document  |  1994-06-07  |  22.8 KB  |  672 lines  |  [oODC/obnF]

  1. Documents.StdDocumentDesc
  2. Documents.DocumentDesc
  3. Containers.ViewDesc
  4. Views.ViewDesc
  5. Stores.StoreDesc
  6. Documents.ModelDesc
  7. Containers.ModelDesc
  8. Models.ModelDesc
  9. Stores.ElemDesc
  10. TextViews.StdViewDesc
  11. TextViews.ViewDesc
  12. TextModels.StdModelDesc
  13. TextModels.ModelDesc
  14. TextModels.AttributesDesc
  15. Geneva
  16. Geneva
  17. Geneva
  18. Geneva
  19. MODULE FormControllers;
  20. (* OmInc 
  21.     IMPORT
  22.         Domains, Ports, Stores, Models, Views, Controllers, Properties, Dialog, Containers,
  23.         FormModels, FormViews;
  24.     CONST
  25.         noSelection* = Containers.noSelection; noFocus* = Containers.noFocus;
  26.         tab = 09X; ltab = 0AX; rdel = 7X; ldel = 8X; line = 0DX; esc = 1BX;
  27.         arrowLeft = 1CX; arrowRight = 1DX; arrowUp = 1EX; arrowDown = 1FX;
  28.         (* range of currently supported versions *)
  29.         minVersion = 0; maxBaseVersion = 0; maxStdVersion = 0;
  30.     TYPE
  31.         Controller* = POINTER TO ControllerDesc;
  32.         ControllerDesc* = RECORD (Containers.ControllerDesc)
  33.             form-: FormModels.Model;
  34.             view-: FormViews.View
  35.         END;
  36.         Directory* = POINTER TO DirectoryDesc;
  37.         DirectoryDesc* = RECORD (Containers.DirectoryDesc) END;
  38.         List* = POINTER TO ListDesc;
  39.         ListDesc* = RECORD
  40.             next*: List;
  41.             view*: Views.View
  42.         END;
  43.         StdController = POINTER TO StdControllerDesc;
  44.         StdControllerDesc = RECORD (ControllerDesc)
  45.             sel: List;    (* (sel = NIL) OR (c.ThisFocus() = NIL) *)
  46.             reader: FormModels.Reader;
  47.             lastX, lastY: LONGINT
  48.         END;
  49.         StdDirectory = POINTER TO StdDirectoryDesc;
  50.         StdDirectoryDesc = RECORD (DirectoryDesc) END;
  51.         MarkMsg = RECORD (Views.Message)
  52.             list: List;
  53.             show: BOOLEAN
  54.         END;
  55.     VAR dir-, stdDir-: Directory;
  56.     (** Controller **)
  57.     PROCEDURE (c: Controller) Clone* (): Controller;
  58.         VAR h: Stores.Store;
  59.     BEGIN
  60.         h := Stores.Clone(c); RETURN h(Controller)
  61.     END Clone;
  62.     PROCEDURE (c: Controller) Internalize* (VAR rd: Stores.Reader);
  63.         VAR tag, thisVersion: SHORTINT;
  64.     BEGIN
  65.         c.Internalize^(rd);
  66.         IF rd.cancelled THEN RETURN END;
  67.         rd.ReadVersion(minVersion, maxBaseVersion, thisVersion)
  68.     END Internalize;
  69.     PROCEDURE (c: Controller) Externalize* (VAR wr: Stores.Writer);
  70.     BEGIN
  71.         c.Externalize^(wr);
  72.         wr.WriteVersion(maxBaseVersion)
  73.     END Externalize;
  74.     PROCEDURE (c: Controller) InitView* (view: Views.View);
  75.         VAR v: FormViews.View;
  76.     BEGIN
  77.         c.InitView^(view);
  78.         IF view # NIL THEN
  79.             ASSERT(view IS FormViews.View, 25);
  80.             c.view := view(FormViews.View); c.form := c.view.ThisModel()
  81.         ELSE
  82.             c.form := NIL; c.view := NIL
  83.         END
  84.     END InitView;
  85.     PROCEDURE (c: Controller) ThisView* (): FormViews.View;
  86.     BEGIN
  87.         RETURN c.view
  88.     END ThisView;
  89.     PROCEDURE (c: Controller) Select* (view: Views.View);
  90.     BEGIN
  91.         HALT(127)
  92.     END Select;
  93.     PROCEDURE (c: Controller) Deselect* (view: Views.View);
  94.     BEGIN
  95.         HALT(127)
  96.     END Deselect;
  97.     PROCEDURE (c: Controller) IsSelected* (view: Views.View): BOOLEAN;
  98.     BEGIN
  99.         HALT(127)
  100.     END IsSelected;
  101.     PROCEDURE (c: Controller) GetSelection* (): List;
  102.     BEGIN
  103.         HALT(127)
  104.     END GetSelection;
  105.     PROCEDURE (c: Controller) SetSelection* (l: List);
  106.     BEGIN
  107.         HALT(127)
  108.     END SetSelection;
  109.     (** Directory **)
  110.     PROCEDURE (d: Directory) NewView* (f: FormModels.Model; opts: SET): FormViews.View;
  111.     BEGIN
  112.         HALT(127)
  113.     END NewView;
  114.     (* auxiliary procedures *)
  115.     PROCEDURE MarkList (c: StdController; f: Views.Frame; h: List; show: BOOLEAN);
  116.         VAR l, t, r, b, s: LONGINT;
  117.     BEGIN
  118.         IF (f.front OR f.target) & ~(Containers.noSelection IN c.opts) THEN
  119.             s := 2 * f.unit;
  120.             WHILE h # NIL DO
  121.                 c.view.GetRect(f, h.view, l, t, r, b);
  122.                 f.MarkRect(l - s, t - s, r + s, b + s, s, Ports.hilite, show);
  123.                 h := h.next
  124.             END
  125.         END
  126.     END MarkList;
  127.     PROCEDURE Toggle (c: StdController; view: Views.View);
  128.     BEGIN
  129.         IF c.IsSelected(view) THEN c.Deselect(view) ELSE c.Select(view) END
  130.     END Toggle;
  131.     (* StdController *)
  132.     PROCEDURE (c: StdController) Internalize (VAR rd: Stores.Reader);
  133.         VAR thisVersion: SHORTINT;
  134.     BEGIN
  135.         c.Internalize^(rd);
  136.         IF rd.cancelled THEN RETURN END;
  137.         rd.ReadVersion(minVersion, maxStdVersion, thisVersion);
  138.         c.sel := NIL; c.lastX := -1
  139.     END Internalize;
  140.     PROCEDURE (c: StdController) Externalize (VAR wr: Stores.Writer);
  141.     BEGIN
  142.         c.Externalize^(wr);
  143.         wr.WriteVersion(maxStdVersion)
  144.     END Externalize;
  145.     PROCEDURE (c: StdController) CopyFrom (source: Controllers.Controller);
  146.     BEGIN
  147.         c.CopyFrom^(source);
  148.         c.sel := NIL; c.lastX := -1
  149.     END CopyFrom;
  150.     PROCEDURE (c: StdController) InitView (view: Views.View);
  151.     BEGIN
  152.         c.InitView^(view);
  153.         c.view.ShowGrid(~(Containers.noSelection IN c.opts))
  154.     END InitView;
  155.     PROCEDURE (c: StdController) RestoreMarks (f: Views.Frame; l, t, r, b: LONGINT);
  156.     BEGIN
  157.         c.RestoreMarks^(f, l, t, r, b);
  158.         IF (c.lastX <= f.l ) OR (c.lastX >= f.r) OR (c.lastY <= f.t) OR (c.lastY >= f.b) THEN
  159.             c.lastX := (f.l + f.r) DIV 2; c.lastY := (f.t + f.b) DIV 2
  160.         END
  161.     END RestoreMarks;
  162.     PROCEDURE (c: StdController) HandleViewMsg (f: Views.Frame;
  163.                                                                                 VAR msg: Views.Message);
  164.     BEGIN
  165.         WITH msg: MarkMsg DO
  166.             MarkList(c, f, msg.list, msg.show)
  167.         ELSE
  168.             c.HandleViewMsg^(f, msg)
  169.         END
  170.     END HandleViewMsg;
  171.     PROCEDURE (c: StdController) SetOpts (opts: SET);
  172.     BEGIN
  173.         c.SetOpts^(opts);
  174.         IF c.view # NIL THEN c.view.ShowGrid(~(noSelection IN c.opts)) END
  175.     END SetOpts;
  176.     (* subclass hooks *)
  177.     PROCEDURE (c: StdController) GetContextType (VAR type: Stores.TypeName);
  178.     BEGIN
  179.         COPY("FormViews.ViewDesc", type)
  180.     END GetContextType;
  181.     PROCEDURE (c: StdController) GetValidOps (VAR valid: SET);
  182.     BEGIN
  183.         valid := {Controllers.pasteChar, Controllers.paste, Controllers.pasteView};
  184.         IF c.sel # NIL THEN valid := valid + {Controllers.cut, Controllers.copy} END
  185.     END GetValidOps;
  186.     PROCEDURE (c: StdController) NativeModel (model: Models.Model): BOOLEAN;
  187.     BEGIN
  188.         ASSERT(model # NIL, 20);
  189.         RETURN model IS FormModels.Model
  190.     END NativeModel;
  191.     PROCEDURE (c: StdController) NativeView (view: Views.View): BOOLEAN;
  192.     BEGIN
  193.         ASSERT(view # NIL, 20);
  194.         RETURN view IS FormViews.View
  195.     END NativeView;
  196.     PROCEDURE (c: StdController) NativeCursorAt (f: Views.Frame; x, y: LONGINT): INTEGER;
  197.     BEGIN
  198.         ASSERT(f # NIL, 20);
  199.         RETURN Ports.graphicsCursor
  200.     END NativeCursorAt;
  201.     PROCEDURE (c: StdController) GetFirstView (selection: BOOLEAN; VAR v: Views.View);
  202.         VAR r: FormModels.Reader;
  203.     BEGIN
  204.         IF selection THEN
  205.             IF c.sel # NIL THEN v := c.sel.view ELSE v := NIL END
  206.         ELSE
  207.             r := c.form.NewReader(c.reader); c.reader := r;
  208.             r.Set(NIL); r.ReadView(v)
  209.         END
  210.     END GetFirstView;
  211.     PROCEDURE (c: StdController) GetNextView (selection: BOOLEAN; VAR v: Views.View);
  212.         VAR h: List; r: FormModels.Reader;
  213.     BEGIN    (* could be optimized *)
  214.         ASSERT(v # NIL, 20);
  215.         IF selection THEN
  216.             h := c.sel; WHILE (h # NIL) & (h.view # v) DO h := h.next END; ASSERT(h # NIL, 21);
  217.             IF h.next # NIL THEN v := h.next.view ELSE v := NIL END
  218.         ELSE
  219.             r := c.form.NewReader(c.reader); c.reader := r;
  220.             r.Set(v); r.ReadView(v)
  221.         END
  222.     END GetNextView;
  223.     PROCEDURE (c: StdController) MarkDropTarget (src, dst: Views.Frame;
  224.                                                                                     sx, sy, dx, dy: LONGINT;
  225.                                                                                     show: BOOLEAN);
  226.         CONST dm = 4 * Ports.point; dp = 18 * Ports.point;
  227.         VAR vx, vy, l, t, r, b, w, h: LONGINT; sc: Containers.Controller; s: Views.View;
  228.     BEGIN    (* cf. Drop *)
  229.         IF src.view IS FormViews.View THEN
  230.             vx := dx - sx; vy := dy - sy;
  231.             sc := src.view(FormViews.View).ThisController();
  232.             IF sc # NIL THEN
  233.                 WITH sc: Controller DO
  234.                     sc.GetFirstView(Containers.selection, s);
  235.                     WHILE s # NIL DO
  236.                         FormModels.GetRect(s, l, t, r, b); w := r - l; h := b - t;
  237.                         INC(l, vx); INC(t, vy); FormViews.RoundToGrid(c.view, l, t);
  238.                         dst.MarkRect(l, t, l + w, t + h, 0, Ports.invert, show);
  239.                         sc.GetNextView(Containers.selection, s)
  240.                     END
  241.                 END
  242.             END
  243.         ELSE
  244.             FormViews.RoundToGrid(c.view, dx, dy);
  245.             dst.MarkRect(dx - dm, dy, dx + dp, dy + dst.unit, 0, Ports.invert, show);
  246.             dst.MarkRect(dx, dy - dm, dx + dst.unit, dy + dp, 0, Ports.invert, show)
  247.         END
  248.     END MarkDropTarget;
  249.     PROCEDURE (c: StdController) TrackMarks (f: Views.Frame; x, y: LONGINT;
  250.                                                                             units, extend, add: BOOLEAN);
  251.         VAR dx, dy, x0, y0, dx0, dy0: LONGINT; isDown: BOOLEAN; h: Views.View;
  252.         PROCEDURE InvertRect (f: Views.Frame; x, y, dx, dy: LONGINT);
  253.             VAR l, t, r, b: LONGINT;
  254.         BEGIN
  255.             IF dx >= 0 THEN l := x; r := x + dx ELSE l := x + dx; r := x END;
  256.             IF dy >= 0 THEN t := y; b := y + dy ELSE t := y + dy; b := y END;
  257.             f.MarkRect(l, t, r, b, 0, Ports.dim50, TRUE)
  258.         END InvertRect;
  259.         PROCEDURE SelectArea (c: StdController; l, t, r, b: LONGINT; toggle: BOOLEAN);
  260.             VAR h: LONGINT; s: FormModels.Reader; v: Views.View; p, q: List; empty: BOOLEAN;
  261.         BEGIN
  262.             IF l > r THEN h := l; l := r; r := h END;
  263.             IF t > b THEN h := t; t := b; b := h END;
  264.             s := c.form.NewReader(c.reader); c.reader := s;
  265.             s.Set(NIL); s.ReadView(v); p := NIL; empty := c.sel = NIL;
  266.             WHILE v # NIL DO
  267.                 IF (s.l < r) & (s.t < b) & (s.r > l) & (s.b > t) THEN
  268.                     IF toggle THEN Toggle(c, v)
  269.                     ELSIF ~empty THEN c.Select(v)
  270.                     ELSE NEW(q); q.next := p; p := q; q.view := v
  271.                     END
  272.                 END;
  273.                 s.ReadView(v)
  274.             END;
  275.             (* this optimization prevents the appearance of a temporary singleton *)
  276.             IF ~toggle & empty THEN c.SetSelection(p) END
  277.         END SelectArea;
  278.     BEGIN
  279.         dx := 0; dy := 0;    (* vector from (x, y) *)
  280.         InvertRect(f, x, y, dx, dy);
  281.         REPEAT
  282.             f.Input(x0, y0, isDown);
  283.             dx0 := x0 - x; dy0 := y0 - y;
  284.             IF (dx0 # dx) OR (dy0 # dy) THEN
  285.                 InvertRect(f, x, y, dx, dy);
  286.                 dx := dx0; dy := dy0;
  287.                 InvertRect(f, x, y, dx, dy)
  288.             END
  289.         UNTIL ~isDown;
  290.         InvertRect(f, x, y, dx, dy);
  291.         c.lastX := x0; c.lastY := y0;
  292.         IF (dx # 0) OR (dy # 0) THEN
  293.             SelectArea(c, x, y, x + dx, y + dy, extend OR add)
  294.         ELSE
  295.             h := c.form.ViewAt(x, y);
  296.             IF h # NIL THEN
  297.                 IF extend OR add THEN Toggle(c, h) ELSE c.Select(h) END
  298.             END
  299.         END
  300.     END TrackMarks;
  301.     PROCEDURE (c: StdController) Resize (view: Views.View; l, t, r, b: LONGINT);
  302.     BEGIN
  303.         c.form.Resize(view, l, t, r, b)
  304.     END Resize;
  305.     PROCEDURE (c: StdController) DeleteSelection;
  306.         VAR script: Domains.Operation; h: List;
  307.     BEGIN
  308.         Models.BeginScript(c.form, "#System:Deletion", script);
  309.         h := c.sel; WHILE h # NIL DO c.form.Delete(h.view); h := h.next END;
  310.         Models.EndScript(c.form, script)
  311.     END DeleteSelection;
  312.     PROCEDURE (c: StdController) MoveLocalSelection (src, dst: Views.Frame; sx, sy,
  313.                                                                                         dx, dy: LONGINT);
  314.             VAR script: Domains.Operation; sel, h: List;
  315.     BEGIN
  316.         dx := dx - sx; dy := dy - sy;
  317.         IF (dx # 0) OR (dy # 0) THEN
  318.             FormViews.RoundToGrid(c.view, dx, dy);
  319.             sel := c.GetSelection();
  320.             Models.BeginScript(c.form, "#System:Moving", script);
  321.             h := sel; WHILE h # NIL DO c.form.Move(h.view, dx, dy); h := h.next END;
  322.             Models.EndScript(c.form, script);
  323.             c.SetSelection(sel)
  324.         END
  325.     END MoveLocalSelection;
  326.     PROCEDURE (c: StdController) CopyLocalSelection (src, dst: Views.Frame; sx, sy,
  327.                                                                                         dx, dy: LONGINT);
  328.         VAR script: Domains.Operation; q: Views.View; h, s, t: List;
  329.     BEGIN
  330.         dx := dx - sx; dy := dy - sy;
  331.         IF (dx # 0) OR (dy # 0) THEN
  332.             FormViews.RoundToGrid(c.view, dx, dy);
  333.             Models.BeginScript(c.form, "#System:Copying", script);
  334.             h := c.GetSelection(); s := NIL;
  335.             WHILE h # NIL DO
  336.                 q := h.view; c.form.Copy(q, dx, dy);
  337.                 NEW(t); t.next := s; s := t; t.view := q;
  338.                 h := h.next
  339.             END;
  340.             Models.EndScript(c.form, script);
  341.             c.SetSelection(s)
  342.         END
  343.     END CopyLocalSelection;
  344.     PROCEDURE (c: StdController) SelectionCopy (): Containers.Model;
  345.         VAR f: FormModels.Model; p: List; w, h, dx, dy, l, t, r, b: LONGINT;
  346.         PROCEDURE GetOffset (f: FormModels.Model; p: List; border: LONGINT; VAR dx, dy: LONGINT);
  347.             VAR l, t, vl, vt, vr, vb: LONGINT;
  348.         BEGIN
  349.             IF p # NIL THEN
  350.                 l := MAX(LONGINT); t := MAX(LONGINT);
  351.                 WHILE p # NIL DO
  352.                     FormModels.GetRect(p.view, vl, vt, vr, vb);
  353.                     IF vl < l THEN l := vl END;
  354.                     IF vt < t THEN t := vt END;
  355.                     p := p.next
  356.                 END;
  357.                 dx := l - border; dy := t - border
  358.             END
  359.         END GetOffset;
  360.     BEGIN
  361.         f := c.form.Clone();
  362.         p := c.sel;
  363.         GetOffset(c.form, p, c.view.border, dx, dy);
  364.         WHILE p # NIL DO
  365.             FormModels.GetRect(p.view, l, t, r, b);
  366.             f.Insert(Views.CopyOf(p.view, Views.deep), l - dx, t - dy, r - dx, b - dy);
  367.             p := p.next
  368.         END;
  369.         f.Init;
  370.         RETURN f
  371.     END SelectionCopy;
  372.     PROCEDURE (c: StdController) NativePaste (m: Models.Model; f: Views.Frame);
  373.         VAR x, y, cw, ch, l, t, r, b: LONGINT; p: Views.View; s: FormModels.Reader;
  374.             n, i: INTEGER;
  375.     BEGIN
  376.         x := c.lastX; y := c.lastY;
  377.         c.view.context.GetSize(cw, ch);
  378.         IF (x <= f.l) OR (x >= f.r) OR (y <= f.t) OR (y >= f.b) THEN
  379.             x := (f.l + f.r) DIV 2; y := (f.r + f.b) DIV 2
  380.         END;
  381.         c.lastX := x; c.lastY := y;
  382.         FormViews.RoundToGrid(c.view, x, y);
  383.         WITH m: FormModels.Model DO
  384.             s := m.NewReader(NIL);
  385.             s.Set(NIL); s.ReadView(p); n := 0;
  386.             WHILE p # NIL DO
  387.                 FormModels.GetRect(p, l, t, r, b);
  388.                 c.form.Insert(Views.CopyOf(p, Views.deep), x + l, y + t, x + r, y + b); INC(n);
  389.                 s.ReadView(p)
  390.             END;
  391.             (* n views have been inserted at the top => select them *)
  392.             c.SelectAll(Containers.deselect);
  393.             i := c.form.NofViews() - n; ASSERT(i >= 0, 100);
  394.             s := c.form.NewReader(s);
  395.             s.Set(NIL); WHILE i # 0 DO s.ReadView(p); DEC(i) END;    (* skip old views *)
  396.             WHILE n # 0 DO s.ReadView(p); c.Select(p); DEC(n) END
  397.         END
  398.     END NativePaste;
  399.     PROCEDURE (c: StdController) ArrowChar (f: Views.Frame; ch: CHAR; units,  select: BOOLEAN);
  400.         VAR d: LONGINT;
  401.     BEGIN
  402.         d := c.view.grid;
  403.         IF units THEN d := d * c.view.gridFactor END;
  404.         IF ch = arrowLeft THEN
  405.             c.MoveLocalSelection(f, f, 0, 0, -d, 0)
  406.         ELSIF ch = arrowRight THEN
  407.             c.MoveLocalSelection(f, f, 0, 0, +d, 0)
  408.         ELSIF ch = arrowUp THEN
  409.             c.MoveLocalSelection(f, f, 0, 0, 0, -d)
  410.         ELSIF ch = arrowDown THEN
  411.             c.MoveLocalSelection(f, f, 0, 0, 0, +d)
  412.         END
  413.     END ArrowChar;
  414.     PROCEDURE (c: StdController) ControlChar (f: Views.Frame; ch: CHAR);
  415.     BEGIN
  416.         IF (ch = ldel) OR (ch = rdel) THEN c.DeleteSelection END
  417.     END ControlChar;
  418.     PROCEDURE (c: StdController) PasteChar (ch: CHAR);
  419.     END PasteChar;
  420.     PROCEDURE (c: StdController) PasteLChar (ch: Containers.LONGCHAR);
  421.     END PasteLChar;
  422.     PROCEDURE (c: StdController) PasteView (f: Views.Frame; v: Views.View;
  423.                                                                             w, h: LONGINT);
  424.         VAR minW, maxW, minH, maxH, x, y: LONGINT;
  425.     BEGIN
  426.         x := c.lastX; y := c.lastY;
  427.         IF (x <= f.l) OR (x >= f.r) OR (y <= f.t) OR (y >= f.b) THEN
  428.             x := (f.l + f.r) DIV 2; y := (f.t + f.b) DIV 2
  429.         END;
  430.         c.lastX := x; c.lastY := y;
  431.         FormViews.RoundToGrid(c.view, x, y);
  432.         c.form.GetEmbeddingLimits(minW, maxW, minH, maxH);
  433.         Properties.PreferredSize(v, minW, maxW, minH, maxH, minW, minH, w, h);
  434.         c.form.Insert(v, x, y, x + w, y + h); c.Select(v)
  435.     END PasteView;
  436.     PROCEDURE (c: StdController) Drop (src, dst: Views.Frame; sx, sy, dx, dy,
  437.                                                                 w, h: LONGINT; v: Views.View);
  438.         VAR minW, maxW, minH, maxH, vx, vy, l, t, r, b: LONGINT;
  439.             sc: Containers.Controller; s: Views.View; p, q: List;
  440.     BEGIN    (* cf. MarkDropTarget *)
  441.         IF src.view IS FormViews.View THEN
  442.             vx := dx - sx; vy := dy - sy;
  443.             sc := src.view(FormViews.View).ThisController();
  444.             IF sc # NIL THEN
  445.                 WITH sc: Controller DO
  446.                     sc.GetFirstView(Containers.selection, s); p := NIL;
  447.                     WHILE s # NIL DO
  448.                         FormModels.GetRect(s, l, t, r, b); w := r - l; h := b - t;
  449.                         v := Views.CopyOf(s, Views.deep);
  450.                         INC(l, vx); INC(t, vy); FormViews.RoundToGrid(c.view, l, t);
  451.                         c.form.Insert(v, l, t, l + w, t + h);
  452.                         NEW(q); q.view := v; q.next := p; p := q;
  453.                         sc.GetNextView(Containers.selection, s)
  454.                     END;
  455.                     c.SetSelection(p)
  456.                 END
  457.             ELSE
  458.                 v := Views.CopyOf(v, Views.deep);
  459.                 FormViews.RoundToGrid(c.view, dx, dy);
  460.                 c.form.GetEmbeddingLimits(minW, maxW, minH, maxH);
  461.                 Properties.PreferredSize(v, minW, maxW, minH, maxH, minW, minH, w, h);
  462.                 c.form.Insert(v, dx, dy, dx + w, dy + h); c.Select(v)
  463.             END
  464.         ELSE
  465.             v := Views.CopyOf(v, Views.deep);
  466.             FormViews.RoundToGrid(c.view, dx, dy);
  467.             c.form.GetEmbeddingLimits(minW, maxW, minH, maxH);
  468.             Properties.PreferredSize(v, minW, maxW, minH, maxH, minW, minH, w, h);
  469.             c.form.Insert(v, dx, dy, dx + w, dy + h); c.Select(v)
  470.         END
  471.     END Drop;
  472.     (* selection *)
  473.     PROCEDURE (c: StdController) HasSelection (): BOOLEAN;
  474.     BEGIN
  475.         RETURN c.sel # NIL
  476.     END HasSelection;
  477.     PROCEDURE (c: StdController) Selectable (): BOOLEAN;
  478.     BEGIN
  479.         RETURN c.form.NofViews() # 0
  480.     END Selectable;
  481.     PROCEDURE (c: StdController) SetSingleton (s: Views.View);
  482.         VAR l: List;
  483.     BEGIN
  484.         c.SetSingleton^(s);
  485.         IF s # NIL THEN NEW(l); l.view := s; c.sel := l ELSE c.sel := NIL END
  486.     END SetSingleton;
  487.     PROCEDURE (c: StdController) SelectAll (select: BOOLEAN);
  488.         VAR s: FormModels.Reader; v: Views.View; l, h: List; msg: MarkMsg;
  489.     BEGIN
  490.         IF select THEN
  491.             ASSERT(~(Containers.noSelection IN c.opts), 20);
  492.             c.SetFocus(NIL);
  493.             s := c.form.NewReader(c.reader); c.reader := s;
  494.             s.Set(NIL); s.ReadView(v);
  495.             IF c.form.NofViews() = 1 THEN
  496.                 ASSERT(v # NIL, 100);
  497.                 c.SetSingleton(v)
  498.             ELSE
  499.                 IF (c.sel # NIL) & (c.sel.next = NIL) THEN c.SetSingleton(NIL) END;
  500.                 l := NIL;
  501.                 WHILE v # NIL DO
  502.                     IF ~c.IsSelected(v) THEN NEW(h); h.next := l; l := h; h.view := v END;
  503.                     s.ReadView(v)
  504.                 END;
  505.                 msg.list := l; c.sel := l; msg.show := TRUE; Views.Broadcast(c.view, msg)
  506.             END
  507.         ELSIF c.sel # NIL THEN
  508.             IF c.sel.next = NIL THEN    (* singleton *)
  509.                 c.SetSingleton(NIL)
  510.             ELSE
  511.                 msg.list := c.sel; c.sel := NIL; msg.show := FALSE; Views.Broadcast(c.view, msg)
  512.             END
  513.         END
  514.     END SelectAll;
  515.     PROCEDURE (c: StdController) InSelection (f: Views.Frame; x, y: LONGINT): BOOLEAN;
  516.         VAR g: Views.Frame;
  517.     BEGIN
  518.         g := Views.FrameAt(f, x, y);
  519.         IF g # NIL THEN
  520.             RETURN c.IsSelected(g.view)
  521.         ELSE
  522.             RETURN FALSE
  523.         END
  524.     END InSelection;
  525.     PROCEDURE (c: StdController) MarkSelection (f: Views.Frame; show: BOOLEAN);
  526.     BEGIN
  527.         IF c.sel = NIL THEN    (* skip *)
  528.         ELSIF c.sel.next = NIL THEN
  529.             Containers.MarkSingleton(c, f, show)
  530.         ELSE
  531.             MarkList(c, f, c.sel, show)
  532.         END
  533.     END MarkSelection;
  534.     (* caret *)
  535.     PROCEDURE (c: StdController) HasCaret (): BOOLEAN;
  536.     BEGIN
  537.         RETURN TRUE
  538.     END HasCaret;
  539.     PROCEDURE (c: StdController) MarkCaret (f: Views.Frame; show: BOOLEAN);
  540.     END MarkCaret;
  541.     (* FormController protocol *)
  542.     PROCEDURE (c: StdController) Select (view: Views.View);
  543.         VAR l, h, sel: List; msg: MarkMsg;
  544.     BEGIN
  545.         ASSERT(view # NIL, 20); ASSERT(view.context.ThisModel() = c.form, 21);
  546.         ASSERT(~(Containers.noSelection IN c.opts), 22);
  547.         l := c.sel; WHILE (l # NIL) & (l.view # view) DO l := l.next END;
  548.         IF l = NIL THEN    (* view is not yet selected *)
  549.             sel := c.sel;
  550.             IF sel = NIL THEN
  551.                 c.SetSingleton(view)
  552.             ELSE
  553.                 NEW(l); l.view := view;
  554.                 IF sel.next = NIL THEN
  555.                     c.SetSingleton(NIL); ASSERT(c.sel = NIL, 100);
  556.                     l.next := sel; c.sel := l;
  557.                     msg.list := l
  558.                 ELSE
  559.                     l.next := sel; c.sel := l;
  560.                     NEW(h); h.view := view;
  561.                     msg.list := h
  562.                 END;
  563.                 msg.show := TRUE; Views.Broadcast(c.view, msg)
  564.             END
  565.         END
  566.     END Select;
  567.     PROCEDURE (c: StdController) Deselect (view: Views.View);
  568.         VAR l, h: List; msg: MarkMsg;
  569.     BEGIN
  570.         ASSERT(view # NIL, 20); ASSERT(view.context.ThisModel() = c.form, 21);
  571.         l := c.sel; h := NIL; WHILE (l # NIL) & (l.view # view) DO h := l; l := l.next END;
  572.         IF l # NIL THEN    (* l is selection node of view, h its predecessor *)
  573.             IF (h = NIL) & (l.next = NIL) THEN    (* singleton *)
  574.                 c.SetSingleton(NIL)
  575.             ELSE
  576.                 IF h = NIL THEN c.sel := l.next ELSE h.next := l.next END;
  577.                 msg.list:= l; l.next := NIL; msg.show := FALSE; Views.Broadcast(c.view, msg);
  578.                 IF (c.sel # NIL) & (c.sel.next = NIL) THEN    (* singleton *)
  579.                     view := c.sel.view;
  580.                     msg.list := c.sel; c.sel := NIL; msg.show := TRUE; Views.Broadcast(c.view, msg);
  581.                     c.SetSingleton(view)
  582.                 END
  583.             END
  584.         END
  585.     END Deselect;
  586.     PROCEDURE (c: StdController) IsSelected (view: Views.View): BOOLEAN;
  587.         VAR l: List;
  588.     BEGIN
  589.         ASSERT(view # NIL, 20); ASSERT(view.context.ThisModel() = c.form, 21);
  590.         l := c.sel; WHILE (l # NIL) & (l.view # view) DO l := l.next END;
  591.         RETURN l # NIL
  592.     END IsSelected;
  593.     PROCEDURE (c: StdController) GetSelection (): List;
  594.         VAR l, h, s: List;
  595.     BEGIN
  596.         l := NIL; s := c.sel;
  597.         WHILE s # NIL DO NEW(h); h.next := l; l := h; h.view := s.view; s := s.next END;
  598.         RETURN l
  599.     END GetSelection;
  600.     PROCEDURE (c: StdController) SetSelection (l: List);
  601.         VAR msg: MarkMsg;
  602.     BEGIN
  603.         c.SelectAll(FALSE); ASSERT(c.sel = NIL, 100);
  604.         IF l = NIL THEN    (* skip *)
  605.         ELSIF l.next = NIL THEN
  606.             c.SetSingleton(l.view)
  607.         ELSE
  608.             msg.list := l; c.sel := l; msg.show := TRUE; Views.Broadcast(c.view, msg)
  609.         END
  610.     END SetSelection;
  611.     (* StdDirectory *)
  612.     PROCEDURE (d: StdDirectory) NewController (opts: SET): Controller;
  613.         VAR c: StdController;
  614.     BEGIN
  615.         NEW(c); c.SetOpts(opts); c.Init; RETURN c
  616.     END NewController;
  617.     PROCEDURE (d: StdDirectory) NewView (f: FormModels.Model; opts: SET): FormViews.View;
  618.         VAR c: Containers.Controller; v: FormViews.View;
  619.     BEGIN
  620.         v := FormViews.dir.New(f); c := v.ThisController();
  621.         IF c # NIL THEN c.SetOpts(opts) ELSE v.SetController(d.NewController(opts)) END;
  622.         RETURN v
  623.     END NewView;
  624.     (** miscellaneous **)
  625.     PROCEDURE Focus* (): Controller;
  626.         VAR v: Views.View; c: Controllers.Controller;
  627.     BEGIN
  628.         v := Controllers.FocusView();
  629.         IF (v # NIL) & (v IS FormViews.View) THEN
  630.             c := v(FormViews.View).ThisController();
  631.             IF (c # NIL) & (c IS Controller) THEN
  632.                 RETURN c(Controller)
  633.             ELSE RETURN NIL
  634.             END
  635.         ELSE RETURN NIL
  636.         END
  637.     END Focus;
  638.     PROCEDURE Insert* (c: Controller; view: Views.View; l, t, r, b: LONGINT);
  639.         VAR w, h: LONGINT;
  640.     BEGIN
  641.         w := r - l; h := b - t;
  642.         FormViews.RoundToGrid(c.view, l, t);
  643.         c.form.Insert(view, l, t, l + w, t + h)
  644.     END Insert;
  645.     PROCEDURE SetDir* (d: Directory);
  646.     BEGIN
  647.         ASSERT(d # NIL, 20); dir := d
  648.     END SetDir;
  649.     PROCEDURE Install*;
  650.     BEGIN
  651.         FormViews.SetCtrlDir(dir)
  652.     END Install;
  653.     PROCEDURE Init;
  654.         VAR d: StdDirectory;
  655.     BEGIN
  656.         NEW(d); SetDir(d); stdDir := d
  657.     END Init;
  658. BEGIN
  659.     Init
  660. END FormControllers.
  661. TextControllers.StdCtrlDesc
  662. TextControllers.ControllerDesc
  663. Containers.ControllerDesc
  664. Controllers.ControllerDesc
  665. TextRulers.StdRulerDesc
  666. TextRulers.RulerDesc
  667. TextRulers.StdStyleDesc
  668. TextRulers.StyleDesc
  669. TextRulers.AttributesDesc
  670. Geneva
  671. Documents.ControllerDesc
  672.